import src.FileParser;
import src.FileWriter;
import src.Parametros;


public class Tp_Ej1_Main {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		String nombreArchivo = "Tp1";
		
		String archivoEntrada = ".\\resources\\" + nombreArchivo + "Ej1.in";
		String archivoSalida = ".\\resources\\" + nombreArchivo + "Ej1.out";
		String archivoTiempos = ".\\resources\\" + nombreArchivo + "Ej1.time";
		
		algoritmo(archivoEntrada, archivoSalida, archivoTiempos);
	}
	
	private static void algoritmo(String archivoEntrada, String archivoSalida, String archivoTiempos) {
		FileParser fp = new FileParser(archivoEntrada);
		FileWriter fw = new FileWriter(archivoSalida);
		FileWriter fwTiempos = new FileWriter(archivoTiempos);
		int cantidadRepeticiones=5;
		long minMedicion=0;
		long res=0;
		
		while (!((fp.getLine().trim()).equals("-1 -1"))){
			Parametros instancia = parsearInstancia(fp);
			for (int rep=0 ;rep<cantidadRepeticiones;rep++){
				long tiempoInicio = System.nanoTime();
				res = modulo(instancia);
				long totalTiempo = System.nanoTime()- tiempoInicio;
				minMedicion+=totalTiempo;
			}
			minMedicion /= cantidadRepeticiones;
			fwTiempos.writeLine(instancia.getN() + " " + String.valueOf(minMedicion)); 
			System.out.println("El resultado de la instancia es: " + res);
			fw.writeLine(String.valueOf(res));
		}
		
		fp.closeFile();
		fw.closeFile();
		fwTiempos.closeFile();
	}
	
	private static Parametros parsearInstancia(FileParser fp) {
		Parametros res = new Parametros();
		String[] str = fp.getLine().trim().replaceAll("\\s+", " ").split("\\s");
		
		res.setB(Integer.parseInt(str[0]));
		res.setN(Integer.parseInt(str[1]));
		
		fp.nextLine();
		return res;
	}
	
	private static long modulo(Parametros instancia) {
		long nCociente = instancia.getN();
		long resultado = 1;
		long cuadradoParcial = instancia.getB();
		
		if (instancia.getN()==1)
			return 0;
		
		while (1 <= nCociente / 2) {
			if (nCociente % 2 == 1) { 	// suponemos que esta pensando que esta terminando... 
										// por eso setea el resultado
				resultado *= cuadradoParcial;
				if (resultado > instancia.getN())
					resultado %= instancia.getN();
			}
			
			nCociente /= 2;
			
			cuadradoParcial *= cuadradoParcial;
			
			if (cuadradoParcial > instancia.getN())
				cuadradoParcial %= instancia.getN();// en cada iteracion me quedo con el resto del 
													// cuadradoParcial. Con esto logro trabajar con numeros
													// de igual congruencia y menores al n original... ver grafico de mariano!!!
			
			if (resultado == 0 || cuadradoParcial == 0) // esto es por si el b de entrada es 0.
				return 0;
		}			
		resultado *= cuadradoParcial;
		if (resultado > instancia.getN())
			resultado %= instancia.getN();
		return resultado;
	}
	
}
